﻿using GDotnet.Reader.Api.DAL;
using GDotnet.Reader.Api.Protocol.Gx;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BtLabelTool
{
    public class RfidHelper
    {
        public static GClient clientConn = new GClient();
        /// <summary>
        /// 读卡器
        /// </summary>
        public static List<string> devList = new List<string>();
        /// <summary>
        /// 读到的标签
        /// </summary>
        public static List<string> readLables = new List<string>();
        /// <summary>
        /// 点亮的标签
        /// </summary>
        public static List<string> lightLables = new List<string>();
        /// <summary>
        /// 打开读卡器
        /// </summary>
        /// <returns></returns>
        public static bool OpenRfid_USB_HID()
        {
            try
            {
                devList.Clear();
                devList = GClient.GetUsbHidList();
                if (devList.Count != 1)
                {
                    return false;
                }
                eConnectionAttemptEventStatusType status;
                if (clientConn.OpenUsbHid(devList[0], IntPtr.Zero, 3000, out status))
                {
                    // subscribe to event
                    clientConn.OnEncapedTagEpcLog += new delegateEncapedTagEpcLog(OnEncapedTagEpcLog);
                    clientConn.OnEncapedTagEpcOver += new delegateEncapedTagEpcOver(OnEncapedTagEpcOver);

                }
                return true;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// 关闭读卡器
        /// </summary>
        /// <returns></returns>
        public static bool CloseRfid_USB_HID()
        {
            try
            {
                if (devList.Count != 1)
                {
                    return true;
                }
                devList.Clear();
                clientConn.Close();
                return true;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// 读取EPC标签
        /// </summary>
        /// <param name="count">数量</param>
        /// <returns></returns>
        public static List<string> ReadRfidEPC(int count)
        {
            try
            {
                readLables.Clear();
                lightLables.Clear();
                if (devList.Count != 1)
                {
                    return new List<string>();
                }
                MsgBaseStop msgBaseStop = new MsgBaseStop();
                clientConn.SendSynMsg(msgBaseStop);
                // 4 antenna read Inventory, EPC & TID
                MsgBaseInventoryEpc msgBaseInventoryEpc = new MsgBaseInventoryEpc();
                msgBaseInventoryEpc.AntennaEnable = (uint)(eAntennaNo._1 | eAntennaNo._2 | eAntennaNo._3 | eAntennaNo._4);
                msgBaseInventoryEpc.InventoryMode = (byte)eInventoryMode.Inventory;
                msgBaseInventoryEpc.ReadTid = new ParamEpcReadTid();                // tid Param
                msgBaseInventoryEpc.ReadTid.Mode = (byte)eParamTidMode.Auto;
                msgBaseInventoryEpc.ReadTid.Len = 6;
                clientConn.SendSynMsg(msgBaseInventoryEpc);
                //循环读取到指定数量的标签超时10s
                int a = 0;
                while (readLables.Count < count && a < 10)
                {
                    CommonHelper.Delay(1000);
                    a++;
                }
                clientConn.SendSynMsg(msgBaseStop);
                return readLables;
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }
        /// <summary>
        /// 点亮标签
        /// </summary>
        /// <param name="filterEpc"></param>
        /// <returns></returns>
        public static bool LightRfid(string filterEpc)
        {
            try
            {
                if (devList.Count != 1)
                {
                    return false;
                }
                MsgBaseStop msgBaseStop = new MsgBaseStop();
                clientConn.SendSynMsg(msgBaseStop);
                // 4 antenna read Inventory, EPC & TID
                lightLables.Clear();
                readLables.Clear();
                MsgBaseInventoryEpc msgBaseInventoryEpc = new MsgBaseInventoryEpc();
                msgBaseInventoryEpc.AntennaEnable = (uint)(eAntennaNo._1 | eAntennaNo._2 | eAntennaNo._3 | eAntennaNo._4);
                msgBaseInventoryEpc.InventoryMode = (byte)eInventoryMode.Inventory;
                msgBaseInventoryEpc.Filter = new ParamEpcFilter();
                msgBaseInventoryEpc.Filter.Area = (byte)eEpcWriteArea.Epc;
                msgBaseInventoryEpc.Filter.BitStart = 32;
                msgBaseInventoryEpc.Filter.HexData = filterEpc;
                msgBaseInventoryEpc.Filter.BData = GDotnet.Reader.Api.Utils.Util.ConvertHexStringToByteArray(msgBaseInventoryEpc.Filter.HexData);
                msgBaseInventoryEpc.Filter.BitLength = (byte)(msgBaseInventoryEpc.Filter.BData.Length * 8);
                msgBaseInventoryEpc.ReadReserved = new ParamEpcReadReserved();                // tid Param
                msgBaseInventoryEpc.ReadReserved.Start = 4;
                msgBaseInventoryEpc.ReadReserved.Len = 1;
                //读取
                clientConn.SendSynMsg(msgBaseInventoryEpc);
                //添加点亮标签用于Api事件处理
                lightLables.Add(filterEpc);
                //等待点亮超时3s
                int a = 0;
                while (readLables.Count == 0 && a < 60)
                {
                    CommonHelper.Delay(50);
                    a++;
                }
                //readLables为点亮的标签
                if (readLables.Count == 0)
                {
                    clientConn.SendSynMsg(msgBaseStop);
                    return false;
                }
                CommonHelper.Delay(1500);
                clientConn.SendSynMsg(msgBaseStop);
                return true;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// 写入标签
        /// </summary>
        /// <param name="sWriteHexData"></param>
        /// <returns></returns>
        public static bool WriteRfidEPC(String sWriteHexData)
        {
            try
            {
                if (devList.Count != 1)
                {
                    return false;
                }
                MsgBaseStop msgBaseStop = new MsgBaseStop();
                clientConn.SendSynMsg(msgBaseStop);
                // write EPC， hex 1234
                MsgBaseWriteEpc msgBaseWriteEpc = new MsgBaseWriteEpc();
                msgBaseWriteEpc.AntennaEnable = (ushort)eAntennaNo._1;
                msgBaseWriteEpc.Area = (byte)eEpcWriteArea.Epc;
                msgBaseWriteEpc.Start = 1;
                //生成写入值
                int iWordLen = sWriteHexData.Length / 4;                            // 1 word = 2 byte     
                ushort iPc = (ushort)(iWordLen << 11);
                String sPc = Convert.ToString(iPc, 16).PadLeft(4, '0');
                sWriteHexData = sPc + sWriteHexData;                                // 
                msgBaseWriteEpc.HexWriteData = sWriteHexData.Trim().PadRight(iWordLen * 4, '0');
                // /* If you need to write data with a special encoding, encode it yourself and use the "BwriteData" property */
                // msgBaseWriteEpc.BwriteData = Util.ConvertHexStringToByteArray(msgBaseWriteEpc.HexWriteData);

                // /* Matching the TID write tag example for writing a single tag in a multi-tag environment */
                //String filterTid = "E2801160200061CB22BC0916";
                //msgBaseWriteEpc.Filter = new ParamEpcFilter();
                //msgBaseWriteEpc.Filter.Area = (byte)eParamFilterArea.TID;
                //msgBaseWriteEpc.Filter.BitStart = 0;
                //msgBaseWriteEpc.Filter.HexData = filterTid;
                //msgBaseWriteEpc.Filter.BData = Util.ConvertHexStringToByteArray(msgBaseWriteEpc.Filter.HexData);
                //msgBaseWriteEpc.Filter.BitLength = (byte)(msgBaseWriteEpc.Filter.BData.Length * 8);

                ///* match epc */
                //String filterEpc = "4321";
                //Console.WriteLine("Filter hex " + filterEpc);
                //msgBaseWriteEpc.Filter = new ParamEpcFilter();
                //msgBaseWriteEpc.Filter.Area = (byte)eParamFilterArea.EPC;
                //msgBaseWriteEpc.Filter.BitStart = 32;
                //msgBaseWriteEpc.Filter.HexData = filterEpc;
                //// msgBaseWriteEpc.Filter.BData = Util.ConvertHexStringToByteArray(msgBaseWriteEpc.Filter.HexData);
                //msgBaseWriteEpc.Filter.BitLength = (byte)(msgBaseWriteEpc.Filter.BData.Length * 8);

                clientConn.SendSynMsg(msgBaseWriteEpc);
                CommonHelper.Delay(500);
                clientConn.SendSynMsg(msgBaseStop);
                return true;

            }
            catch (Exception ex)
            {

                throw ex;
            }
        }
        #region API事件

        public static void OnEncapedTagEpcLog(EncapedLogBaseEpcInfo msg)
        {
            // Any blocking inside the callback will affect the normal use of the API !
            // 回调里面的任何阻塞或者效率过低，都会影响API的正常使用 !
            

            if (lightLables.Count > 0)
            {            
                //点亮标签
                if (null != msg && lightLables.Contains(msg.logBaseEpcInfo.Epc))
                {
                    readLables.Add(msg.logBaseEpcInfo.Epc);
                }
            }
            else
            {           
                //读取标签
                if (null != msg && 0 == msg.logBaseEpcInfo.Result)
                {
                    //Console.WriteLine(":ant[" + msg.logBaseEpcInfo.AntId + "]" + msg.logBaseEpcInfo.Epc + "|" + msg.logBaseEpcInfo.Tid);
                    if (readLables.Contains(msg.logBaseEpcInfo.Epc) == false)
                    {
                        readLables.Add(msg.logBaseEpcInfo.Epc);
                    }
                }
            }
        }
        public static void OnEncapedTagEpcOver(EncapedLogBaseEpcOver msg)
        {
            if (null != msg)
            {
                //Console.WriteLine("Epc log over.");


            }
        }

        #endregion
    }
}
